home *** CD-ROM | disk | FTP | other *** search
Text File | 1995-05-20 | 11.5 KB | 456 lines | [TEXT/PJMM] |
-
- { Modal Dialog TextEdit useritem snippet}
- { Steve Falkenburg-- MacDTS}
-
- { This snippet shows the steps necessary to implement a scrolling, editable text field}
- { in a dialog. You may want to do this if you will be requiring the user to enter more than}
- { 255 characters (the limit for editText items), if you want a different font for several}
- { different editText items, or it you want to add scrolling support to an editible text item.}
-
- program ModalTextEdit;
-
- { constants}
-
- const
- kMyDialog = 128;
- {kInFront = WindowPtr(-1);}
- kEditTextItem = 2;
- kScrollerItem = 3;
- kMargin = 4;
- kPageLines = 16;
- kScrollToTop = 0;
- kScrollToBottom = 1;
- kMaxLines = 128;
- kCheckOneItem = 5;
- kCheckTwoItem = 6;
-
-
- (* initialize the Mac managers *)
-
- procedure InitStuff;
- begin
- {$IFC UNDEFINED THINK_PASCAL}
- InitGraf(@qd.thePort);
- InitFonts;
- InitWindows;
- InitMenus;
- TEInit;
- InitDialogs(nil);
- {$ENDC}
- InitCursor;
- FlushEvents(everyEvent, 0);
- end;
-
- (* utility procedure to return a handle to the scrollbar control*)
-
- function GetScrollBar (theDialog: DialogPtr): ControlHandle;
- var
- theScroller: ControlHandle;
- iType: Integer;
- iRect: Rect;
- begin
- GetDItem(theDialog, kScrollerItem, iType, Handle(theScroller), iRect);
- GetScrollBar := theScroller;
- end; {GetScrollBar}
-
-
- (* utility procedure to return the textedit record for the given dialog *)
-
- function GetTEHandle (theDialog: DialogPtr): TEHandle;
- begin
- GetTEHandle := TEHandle(GetWRefCon(WindowPtr(theDialog)));
- end;
-
-
- (* dialog user item draw procedure for text box. It just calls FrameRect *)
-
- procedure EditTextDrawProc (theDialog: DialogPtr; theItem: Integer);
- var
- iType: Integer;
- iHndl: Handle;
- iRect: Rect;
- savePort: GrafPtr;
- begin
- GetPort(savePort);
- SetPort(theDialog);
-
- GetDItem(theDialog, theItem, iType, iHndl, iRect);
- FrameRect(iRect);
-
- SetPort(savePort);
- end; {EditTextDrawProc}
-
-
-
- (* sets the text top line to be the same as the current scrollbar position. this is called after}
- { a thumb movement in the scrollbar.}
- {*)
-
- procedure ReAlignTextToScrollbar (theDialog: DialogPtr);
- var
- theTE: TEHandle;
- scrollBar: ControlHandle;
- controlScrollPosition, textScrollPosition, scrollDelta, scrollPix: Integer;
- begin
- theTE := GetTEHandle(theDialog);
- scrollBar := GetScrollBar(theDialog);
-
- controlScrollPosition := GetCtlValue(scrollBar);
- textScrollPosition := (theTE^^.viewRect.top - theTE^^.destRect.top) div theTE^^.lineHeight;
- scrollDelta := textScrollPosition - controlScrollPosition;
- scrollPix := scrollDelta * theTE^^.lineHeight;
- TEScroll(0, scrollPix, theTE);
- end; {ReAlignTextToScrollbar}
-
-
- (* sets the scrollbar thumb to the current text position. this is called after autoscrolling,}
- { which may occur after a call to TEKey, or during a drag-scroll}
- {*)
-
- procedure ReAlignScrollbarToText (theDialog: DialogPtr);
- var
- theTE: TEHandle;
- scrollBar: ControlHandle;
- textScrollPosition: Integer;
- begin
- theTE := GetTEHandle(theDialog);
- scrollBar := GetScrollBar(theDialog);
-
- textScrollPosition := (theTE^^.viewRect.top - theTE^^.destRect.top) div theTE^^.lineHeight;
- SetCtlValue(scrollBar, textScrollPosition);
- end; {ReAlignScrollbarToText}
-
-
- (* scrolls the text by the delta passed in to the function. called in response to clicking the*)
- (* arrows or page areas of the scrollbar to move the text*)
-
- procedure ScrollText (theDialog: DialogPtr; lines: Integer);
- var
- theTE: TEHandle;
- scrollPix: Integer;
- textScrollPosition: Integer;
- begin
- theTE := GetTEHandle(theDialog);
-
- textScrollPosition := (theTE^^.viewRect.top - theTE^^.destRect.top) div theTE^^.lineHeight;
- if ((textScrollPosition + lines) < 0) then
- lines := -textScrollPosition;
- if ((textScrollPosition + lines) > kMaxLines) then
- lines := kMaxLines - textScrollPosition;
-
- scrollPix := lines * theTE^^.lineHeight;
-
- TEScroll(0, -scrollPix, theTE);
- end; {ScrollText}
-
-
- { text drag callback procedure. this routine handles drag scrolling by checking to see if we}
- { are in the area where drag-scrolling is necessary, and calling scrolltext followed by a}
- { scrollbar realignment}
-
- function MyTEClickProc: Boolean;
- var
- pt: Point;
- theDialog: DialogPtr;
- theControl: ControlHandle;
- theTE: TEHandle;
- textRect: Rect;
- scrollLines: Integer;
- savePort: GrafPtr;
- saveClip: RgnHandle;
- begin
- GetMouse(pt);
- theDialog := DialogPtr(FrontWindow);
- theTE := GetTEHandle(theDialog);
-
- GetPort(savePort);
- SetPort(theDialog);
-
- saveClip := NewRgn;
- GetClip(saveClip);
- ClipRect(theDialog^.portRect);
-
- scrollLines := 0;
- textRect := theTE^^.viewRect;
- if (pt.v < textRect.top) then
- scrollLines := -1
- else if pt.v > textRect.bottom then
- scrollLines := 1;
-
- if scrollLines <> 0 then
- begin
- ScrollText(theDialog, scrollLines);
- ReAlignScrollbarToText(theDialog);
- end;
-
- SetClip(saveClip);
- DisposeRgn(saveClip);
- SetPort(savePort);
- MyTEClickProc := true;
- end; {MyTEClickProc}
-
-
-
- (* handler for null events. used in our case to blink the insertion point}
- {*)
-
- procedure HandleIdle (theDialog: DialogPtr);
- var
- theTE: TEHandle;
- begin
- theTE := GetTEHandle(theDialog);
- TEIdle(theTE);
- end; {HandleIdle}
-
-
- (* activate event handler. we take this opportunity to call TEActivate to activate the textedit box*)
-
- procedure HandleActivate (theDialog: DialogPtr);
- var
- theTE: TEHandle;
- begin
- theTE := GetTEHandle(theDialog);
- TEActivate(theTE);
- end;
-
- (* trackcontrol callback used to determine which direction to scroll the text, and by how much.}
- { once this is known, the text is scrolled, and the scrollbar adjusted.}
-
- procedure ScrollBarAction (theControl: ControlHandle; part: Integer);
- var
- theDialog: DialogPtr;
- lines: Integer;
- ctlValue, ctlMax, ctlMin: Integer;
- begin
- ctlMax := GetCtlMax(theControl);
- ctlMin := GetCtlMin(theControl);
- ctlValue := GetCtlValue(theControl);
-
- theDialog := theControl^^.contrlOwner;
-
- case part of
- inUpButton:
- lines := -1;
- inDownButton:
- lines := 1;
- inPageUp:
- lines := -kPageLines;
- inPageDown:
- lines := kPageLines;
- otherwise
- exit(ScrollBarAction);
- end; {case}
-
- if ctlValue + lines > ctlMax then
- lines := ctlMax - ctlValue;
- if ctlValue + lines < ctlMin then
- lines := ctlMin - ctlValue;
-
- if lines <> 0 then
- begin
- ScrollText(theDialog, lines);
- SetCtlValue(theControl, ctlValue + lines);
- end;
- end; {ScrollBarAction}
-
- { here, we see which part of the scrollbar was clicked in by calling findcontrol. trackcontrol}
- { is then called with the appropriate action proc if in one of the buttons or page areas. if}
- { in the thumb, the text is simply re-aligned to the new scrollbar position}
-
- procedure HandleScroller (theDialog: DialogPtr; pt: Point);
- var
- part: Integer;
- theControl: ControlHandle;
- begin
- part := FindControl(pt, theDialog, theControl);
- case part of
- inUpButton, inDownButton, inPageUp, inPageDown:
- if TrackControl(theControl, pt, @ScrollBarAction) = 0 then
- ;
- inThumb:
- begin
- if TrackControl(theControl, pt, nil) = 0 then
- ;
- ReAlignTextToScrollbar(theDialog);
- end;
- end; {case}
- end; {HandleScroller}
-
-
- { mouse-down hander. here, we see if the mousedown was in the scrollbar or in the textedit}
- { record. if in the textedit item, we call teclick. If in the scrollbar, we call handlescroller}
- { to do further processing}
-
- function HandleMouse (theDialog: DialogPtr; pt: Point; modifiers: Integer): Boolean;
- var
- iType: Integer;
- iHndl: Handle;
- textRect, scrollerRect: Rect;
- theTE: TEHandle;
- savePort: GrafPtr;
- shiftDown, result: Boolean;
- theControl: ControlHandle;
- part: Integer;
- begin
- GetPort(savePort);
- SetPort(theDialog);
-
- shiftDown := BAnd(modifiers, shiftKey) <> 0;
- GlobalToLocal(pt);
-
- GetDItem(theDialog, kEditTextItem, iType, iHndl, textRect);
- GetDItem(theDialog, kScrollerItem, iType, iHndl, scrollerRect);
-
- if PtInRect(pt, textRect) then
- begin
- theTE := GetTEHandle(theDialog);
- TEClick(pt, shiftDown, theTE);
- result := true;
- end
- else if PtInRect(pt, scrollerRect) then
- begin
- HandleScroller(theDialog, pt);
- result := true;
- end
- else
- result := false;
-
- SetPort(savePort);
-
- HandleMouse := result;
- end; {HandleMouse}
-
-
- { Creates the necessary data structures necessary to use the textedit item in our dialog. A}
- { handle to the TextEdit record is stored in the Dialog's window refCon field.}
-
- procedure SetupDialog (theDialog: DialogPtr);
- var
- iType: Integer;
- iHndl: Handle;
- iRect: Rect;
- theControl: ControlHandle;
- fontNum: Integer;
- theTE: TEHandle;
- begin
- SetPort(theDialog);
-
- GetDItem(theDialog, kScrollerItem, iType, Handle(theControl), iRect); { set up the scroll bar}
- SetCtlMin(theControl, 0); { (it's stored in a CNTL)}
- SetCtlMax(theControl, kMaxLines);
-
- GetDItem(theDialog, kEditTextItem, iType, iHndl, iRect);
- SetDItem(theDialog, kEditTextItem, iType, @EditTextDrawProc, iRect);
-
- InsetRect(iRect, kMargin, kMargin);
-
- GetFNum('geneva', fontNum);
- TextFont(fontNum);
- theTE := TENew(iRect, iRect); { create our textedit item}
- GetFNum('chicago', fontNum);
- TextFont(fontNum);
-
- SetClikLoop(@MyTEClickProc, theTE); { callback for drag-scrolling}
- TEAutoView(true, theTE); { turn auto-scroll on for text entry}
-
- SetWRefCon(theDialog, LongInt(theTE));
- end; {SetupDialog}
-
-
-
- (* free the memory taken by the textedit record before closing the dialog *)
-
- procedure PrepareFreeDialog (theDialog: DialogPtr);
- var
- theTE: TEHandle;
- begin
- theTE := GetTEHandle(theDialog);
- TEDispose(theTE);
- end; {PrepareFreeDialog}
-
-
- (* this is the main dispatcher for events to be passed off to the scroll bar or textedit box.*)
- (* looks sort of like a WaitNextEvent event handler. *)
-
- function MyDialogFilter (theDialog: DialogPtr; var ev: EventRecord; var itemHit: Integer): Boolean;
- var
- theChar: char;
-
- (* dialog filter event handler for keypresses. All keypresses are passed to the textedit box*)
- procedure HandleKeyPress (theDialog: DialogPtr; theChar: char);
- var
- theTE: TEHandle;
- begin
- theTE := GetTEHandle(theDialog);
- TEKey(theChar, theTE);
- ReAlignScrollbarToText(theDialog);
- end;
-
- begin {MyDialogFilter}
- case ev.what of
- keyDown, autoKey:
- begin
- theChar := Char(BAnd(ev.message, charCodeMask));
- HandleKeyPress(theDialog, theChar);
- MyDialogFilter := true;
- end;
- nullEvent:
- begin
- HandleIdle(theDialog);
- MyDialogFilter := false;
- end;
- activateEvt:
- begin
- HandleActivate(theDialog);
- MyDialogFilter := false;
- end;
- mouseDown:
- MyDialogFilter := HandleMouse(theDialog, ev.where, ev.modifiers);
- otherwise
- MyDialogFilter := false;
- end;
- end; {MyDialogFilter}
-
-
- (* display dialog, and handle pretty standard ModalDialog loop. The modal dialog loop doesn't}
- { handle item hits to the scroll bar or text items. These are handled through the filter}
- { procedure}
- {*)
-
- procedure DoDialog;
- var
- theDialog: DialogPtr;
- item: Integer;
- checkBoxControl: ControlHandle;
- iType: Integer;
- iRect: Rect;
- begin
- theDialog := GetNewDialog(kMyDialog, nil, WindowPtr(-1));
- SetupDialog(theDialog);
-
- repeat
- begin
- ModalDialog(@MyDialogFilter, item);
- case item of
- kCheckOneItem, { check boxes}
- kCheckTwoItem:
- begin
- GetDItem(theDialog, item, iType, Handle(checkBoxControl), iRect);
- SetCtlValue(checkBoxControl, Integer(not Boolean(GetCtlValue(checkBoxControl))));
- end;
- end; {case}
- end;
- until item = ok;
-
- PrepareFreeDialog(theDialog);
- DisposeDialog(theDialog);
- end; {DoDialog}
-
-
- (* main entry point *)
-
- begin
- InitStuff;
- DoDialog;
- ExitToShell;
- end.